#ifndef FILEBROWSER_H
#define FILEBROWSER_H

#include "extras/listviewdelegate.h"
#include <QListView>
#include <QStack>
#include <QDirModel>
#include <QFile>
#include <QFileSystemModel>
#include <QMenu>
#include <QUrl>
#include <QTimer>
#include <QDesktopWidget>
#include <QDesktopServices>
#include <QMap>
#include <QApplication>
#include <QAction>
#include <QModelIndex>
#include "contextmenu.h"
#include "ddeviceinformation.h"

QT_BEGIN_NAMESPACE
class QGestureEvent;
class QTapAndHoldGesture;
class QTapGesture;
class QPinchGesture;
class QSwipeGesture;
QT_END_NAMESPACE

/*! \class FileBrowser
    \brief This class provides the list view widget for the browser and the data model
*/
class FileBrowser : public QWidget
{
    Q_OBJECT
public:
    //! Types of view using listview or tableview
    enum ViewMode{icon,list,detail};
    //! Class constructor
    /*!
      Defines user's home directory as the base path of the file browser
      \param parent Parent object
      */
    explicit FileBrowser( QWidget *parent = 0);

    //! Class constructor
    /*!
      Defines homedir as the base path of the file browser
      \param homedir Base path of the file browser
      \param parent Parent object
      */
    explicit FileBrowser( QString homedir, QWidget *parent = 0);

    //void changeDir(QModelIndex index, bool remember=true);

    //! Returns the current path
    /*!
      Returns the current path of the file browser
      */
    QString getCurrentPath();

    //! Returns the data model
    /*!
      Returns the data model used in the file browser
      */
    QFileSystemModel *getDirModel();

    void setContextMenu(ContextMenu * menu);

    //! Returns the mode of the view
    /*!
      Returns the mode of the view. Gives access to ListView::viewMode
      */
    int viewMode();

    //! Returns a pointer to the listview widget
    /*!
      Returns a pointer to the listview widget
      */
    QWidget * listViewWidget();

    //! Returns a pointer to the tableview widget
    /*!
      Returns a pointer to the tableview widget
      */
    QWidget * tableViewWidget();
    //! Returns the current index shown in the file browser
    /*!
      Gets the current index of the widget that is being used
      */
    QModelIndex getCurrentIndex();

 private:
    //! File browser data moodel
    QFileSystemModel *dirModel;
    //! Progress bar object to show directory copy progress
    QProgressBar *copyProgress;
    //! Listview object to show the data model
    QListView *listView;
    //! TableView object to show the data model
    QTableView *tableView;
    //! Base path, i.e. associated to the home button
    QString basePath;
    //! Current path of the file browser. The path of the current index in the data model
    QString currentPath;
    //! Stack of paths for the previous button. Allows go back action
    QStack<QString> history;
    //! Stack of paths for the next button. Allows go next action
    QStack<QString> future;
    //! Context menu for any file in the file borwser
    ContextMenu *fbMenu;

    QShortcut * scCopy;

    //! Delegated class for the view.Designed for overlaying icons. TODO: this shouldn't be used by default
    ListViewDelegate *listdelegate;

    //! Stores the current view mode
    ViewMode currentViewMode;

    //! Stores the index in the data model of a copied file or directory
    QModelIndex copied_resource;
    //! Determines if we have to delete the copied (cut) item
    bool cutResource;
    //! Grants access to the operative system clipboard
    const QClipboard *clipboard;
    //! Mime data associated to the current item in the clipboard
    const QMimeData *mimeData;

    //! Initializes the class
    /*!
      Defines homedir as the base path of the file browser, assigns the data model, the view delagate and the context menu to be used
      \param homedir Base path of the file browser
      */
    void init(QString homedir= QDir::homePath());
    //! Emits signals for updating some widgets
    /*!
      Emits signals for updating some widgets like back, next and up buttons, setting them enabled or not
      */
    void updateActions();
    //! Copies a resource from the clipboard
    /*!
      Copies (phisically) a file or directory stored in the clipboard.
      */
    bool copyFromClipboard();
    //! Returns the root index shown in the file browser
    /*!
      Gets the current root of the widget that is being used
      */
    QModelIndex getRootIndex();

    bool gestureEvent(QGestureEvent *);
    void tapAndHoldTriggered(QTapAndHoldGesture* );
    void tapTriggered(QTapGesture* );

protected:
    bool event(QEvent *event);

public Q_SLOTS:
    //! Sets the current path to home (base path)
    void goHome();
    //! Goes one level up in the directory tree
    void goUp();
    //! Goes to the previous path stored in the history stack
    void goBack();
    //! Goes to the next path stored in the future stack
    void goForward();
    //! Forces the refreshing of the data model to the current path
    void refresh();
    //! Sets the root path to path
    /*!
      Sets the root path to path. In other words, changes the current directory of the file browser to path
      \param path The path to be used
      \param remember Determines if is required to push the current path to the histoy stack
      */
    void setRootPath(const QString& path= QString(), bool remember=true);
    //! Changes the current directory to the value of index in the data model
    /*!
      Changes the current directory to the value of index in the data model
      \param index The index in the data model to be used
      \param remember Determines if is required to push the current path to the histoy stack
      */
    void changeDir(const QModelIndex& index, bool remember=true);
    //! Changes the view mode of the listview widget
    /*!
      Changes the view mode of the listview widget
      \param view Type of view to be used.
      \sa QListView::ViewMode
      */
    void changeView(int view);
    //! Configures some widgets for being used with the icon view mode
    void setIconViewConfiguration();
    //! Configures some widgets for being used with the list view mode
    void setListViewConfiguration();
    //! Configures some widgets for being used with the list view mode
    void setDetailViewConfiguration();
    //! Slot to force treeview column adaptation to content
    void adaptTreeViewColumns ();

    //! Calls context menu
    /*!
      Calls context menu and performs some internal control regarding the visibility of context menu items
      \param point Current position of the mouse pointer
      */
    void menu(QPoint point);

    //! Opens the directory or the file using the propper application
    /*!
      This method opens the current resource (index) in the data model. If the selected resource is a directory,
      it is assigned as the new root of the file browser. If the selected resource is a file, QDesktopServices::openUrl is called
       \sa FileBrowser::changeDir
      */
    void openResource();
    //! Deletes the selected file or directory
    /*!
      Deletes the selected file or directory after user confirmation
      \param index Resource to be deleted
      */
    void deleteResource(QModelIndex index);
    //! Requests conformation before deletion
    /*!
      Requests conformation before deletion of the current selected item
      */
    void deleteResourceRequest();
    //! Deletes the resorce thah has been cut
    /*!
      Deletes the resorce thah has been cut
      */
    void deleteCutResource();
    //! Renames the selected file or directory
    /*!
      Renames the selected file or directory after user input
      */
    void renameResource();
    //! Copies the selected file or directory to the system clipboard
    /*!
      Copies the selected file or directory to the system clipboard
      */
    void copyResourceToBuffer();
    //! Cuts the selected file or directory to the system clipboard
    /*!
      Copies the selected file or directory to the system clipboard and sets the flag FileBrowser::cutResource to true
      */
    void cutResourceToBuffer();
    //! Pastes the content of the system clipboard
    /*!
        Pastes the content of the system clipboard using FileBrowser::copyFromClipboard
        \sa FileBrowser::copyFromClipboard
      */
    void pasteResource();
    //! Copies the source folder into dest
    /*!
        Copies recursively the source folder into dest
      \param source Source directory
      \param dest Destination directory
      */
    bool copyFolder(QString source, QString dest);
    //! Deletes a folder recursively
    /*!
        Deletes a folder recursively
      \param sourceFolder Directory to be deleted
      */
    bool rmFolder(const QString sourceFolder);
    //! Creates a new folder in the current directory
    /*!
        Creates a new folder in the current directory
      */
    bool createFolder();

    //! Sets basePath to path
    /*!
      Sets basePath variable to path, that is an alternative path to user's home directory. Used for home button
      \param path Path to be used as base path
      */
    void setBasePath(QString path);

    //! Sets a widget for an item in the list view
    /*!
      Encapsultes Listview's setItemWidget but using as a parameter a path instead of an index in the data model.
      The path is converted then to an index in the data model.
      \param path Path of the item in the list view
      \param widget The widget to be used for that element of the list view
      */
    void setItemWidget(QString path, QWidget * widget);

    //TODO: decide if this should be extracted from this class
    //! Encapsulates ListViewDelegate::setOverlayStatus
    void setOverlayStatus(QString path, int status=ListViewDelegate::FileModified);
    //! Encapsulates ListViewDelegate::removeOverlayStatus
    void removeOverlayStatus(QString path);
    //! Encapsulates ListViewDelegate::setMap
    void setMap(QMap <qint64, int>*map);

Q_SIGNALS:
    //void elementDropped(QString);
    //void strOutput(QString);
    //void maximizeWindow();
    //! Emitted when the current directory is changed
    void changeDirectory(QString);
    //! Emitted when the current directory is changed in order to enable or disable the button \sa FileBrowser::updateActions
    void setBackButtonEnabled(bool);
    //! Emitted when the current directory is changed in order to enable or disable the button \sa FileBrowser::updateActions
    void setNextButtonEnabled(bool);
    //! Emitted when the current directory is changed in order to enable or disable the button \sa FileBrowser::updateActions
    void setUpButtonEnabled(bool);
};

#endif // FILEBROWSER_H
